//
//  main.m
//  OC_02实例变量可见度_方法
//
//  Created by wyx on 16/2/25.
//  Copyright © 2016年 Apon. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
#pragma mark - 知识点1.实例变量(成员)变量可见度
    /**
     * 3种: @public,@protected,@private.
     * 默认: @protected.
     * 三种之间区别: @public: 本类可以直接访问(->)
                            子类可以直接访问
                            其他类可以直接访问
                   @protected: 本类可以直接访问
                                子类可以直接访问
                                其他类不可以直接访问
                    @private: 本类可以直接访问
                                子类不可以直接访问
                                其他类 不可以直接访问
     * 详见Person.h 文件
     */
#pragma mark - 知识点2.方法
/**
 * [接收者 消息]
 * 接受者: 类和对象.
 * 消息(方法): 类方法(+)和对象方法(-).
 * 详见 Person.h文件
 */
#if 0
#pragma mark - 知识点3.setter,getter 方法
/**
 * 一个实例变量要有一对 setter 和 getter 方法.
 * setter 方法目的,对实例变量赋值
 * getter 方法目的,对实例变量取值
 * 详见: Person.h 文件
 */
    //创建对象.
    Person *per1 = [[Person alloc] init];
    //调用 setter 方法
    [per1 setName:@"张三"];
    //调用 getter 方法
    [per1 name];
    NSString *str = [per1 name];
    NSLog(@"str:%@",str);
    //创建 person2对象
    Person *per2 = [[Person alloc] init];
    [per2 setName:@"ekbdh"];
    [per2 setName:@"skfh"];
    NSLog(@"%@",[per2 name]);
    //注意下面的 Person3并没有开辟新的内存,只是指针指向了 person 内存首地址
    Person *person3 = per2;
    NSLog(@"%@",[person3 name]);
#pragma mark - 知识点4 继承
    /** 
     * 子类继承父类 所有的实例变量和方法
     * OC 中,只有子类和父类两层.
     * OC中是单向继承
     * 继承有传递性.
     
     * Student 类继承于 Person 类, CollegeStudent 类继承于 Student 类.
     * 详见 Student,CollegeStudent 类文件
     */
    // 创建学生对象
    Student *stu1 = [[Student alloc] init];
    // setName方法从父类继承下来
    [stu1 setName:@"li"];
    [stu1 name:@"ki" sex:@"male" age:18];
    [stu1 sayHi];
    /** 在子类中声明特有的实例变量和方法 */

#pragma mark - 知识点5 重写父类方法(overwrite)
    /** 
     * 父类需求无法满足子类需求.
     * 重写父类方法一般是在父类方法基础上添加新的代码段
     
     
     * 详见 Student.m 文件
     */
    //创建一个student 对象
    Student *stu2 = [[Student alloc] init];
    [stu2 name:@"shfsku" sex:@"bmh" age:20];
    [stu2 setGrade:80];
    [stu2 setclassroomName:@"DLS160101"];
    //调用sayHi方法
    [stu2 sayHi];

#pragma mark -  知识点6. 重写初始化方法
    /** 
     * Person 类重写父类的 init 方法.
     * 详见 Person.m 文件.
     */
    Person *per1 = [[Person alloc] init];
    [per1 sayHi];
    Student *stu4 = [[Student alloc] init];
    [stu4 sayHi];
#endif
#pragma mark - 知识点7.自定义初始化方法
    /** 
     * 需求: 通过一个方法,实现了初始化,同事给某些实例变量赋值
     * 详见 Person.h,Person.m 文件
     */
    Person *per1 = [[Person alloc] initWithName:@"Tom"];
    [per1 sayHi];
    Person *per2 = [[Person alloc] initWithName:@"tom" sex:@"ajks" age:20];
    [per2 sayHi];
#pragma mark - 便利构造器
    //构造器为 + 方法
    //返回值为 (intancetype)
    //方法名以类名开头
    //构造器就是方法
    //封装了对象创建和初始化过程
    //详见 Person.h
    /** 创建对象 */
    //Person *per4 = [Person person];
    //Person *per5 = [Person personWithName:@"Tom" sex:@"m" age:20];
    return 0;
}
